#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std; 
class Student {//学生基类 
protected:
    string studentID;//学号 
    string name;//姓名 
    char gender;//性别 

public:
    // 基类构造函数
    Student(string id, string n, char g) : studentID(id), name(n), gender(g) {}
    // 纯虚函数，实现多态性，需要在派生类中实现
    virtual void displayInfo() = 0;  //显示学生信息 
    virtual double totalScore() = 0;  //计算总分 
    virtual bool matchName(string& query) = 0;  //匹配姓名 
    virtual bool matchID(string& query) = 0;   //匹配id 
    virtual ~Student() {}   //析构函数  作用:对象消亡时,自动被调用,用来释放对象占用的空间 
    
};

class TelecomStudent : public Student {//派生类，电信类 
private:
    string className;//班级 
    double mathScore;//高数成绩 
    double englishScore;//英语成绩 

public:
    // 派生类构造函数                                                                  //学生基类的三个字段    派生类新增的三个字段 
    TelecomStudent(string id, string n, char g, string cn, double math, double english) : Student(id, n, g), className(cn), mathScore(math), englishScore(english) {}

    // 重写基类纯虚函数
    //显示学生信息 
    void displayInfo() override {
        cout << "学号: " << studentID << "; ";
        cout << "姓名: " << name << "; ";
        cout << "性别: " << gender << "; ";
        cout << "班级: " << className << "; ";
        cout << "数学成绩: " << mathScore << "; ";
        cout << "英语成绩: " << englishScore << "; " << endl;
    }
    
    // 计算总成绩
    double totalScore() override {
        return mathScore + englishScore;//数学成绩+英语成绩 
    }
    //模糊匹配姓名 
    bool matchName(string& query) override {
        return name.find(query) != string::npos;
    }
	//模糊匹配学生id 
    bool matchID(string& query) override {
        return studentID.find(query) != string::npos;
    }
    //匹配学生id 
    bool findStuById(string& query){
    	return studentID == query;
	}
	//修改学生信息函数 
	void modifyInfo(){
		//就显示提示，提示用户输入修改后的信息即可 
		cout << "请输入新的姓名: ";
        cin >> name;//
        cout << "请输入新的性别: ";
        cin >> gender;
        cout << "请输入新的班级: ";
        cin >> className;
        cout << "请输入新的高数成绩: ";
        cin >> mathScore;
        cout << "请输入新的英语成绩: ";
        cin >> englishScore;
	}

    // 静态成员函数，用于排序
    static bool compareScores(const TelecomStudent& s1, const TelecomStudent& s2) {
    	//先比较高数成绩 
        if (s1.mathScore != s2.mathScore) {//高数成绩不一样时 
            return s1.mathScore > s2.mathScore; //返回高数成绩的比较 
        } else if (s1.englishScore != s2.englishScore) { //高数成绩一样，则比较英语成绩 
            return s1.englishScore > s2.englishScore; //返回英语成绩的比较 
        } else {//两个成绩都一样 
            return s1.studentID < s2.studentID; //返回学号的比较 
        }
    }
	
	virtual ~TelecomStudent() {}   //析构函数  作用:对象消亡时,自动被调用,用来释放对象占用的空间 
};

//判断id是否重复的函数 
bool isDuplicateID(vector<TelecomStudent> students, string id) {//保证id的唯一性 
	for (auto& student : students) {//遍历学生列表 
	    if (student.findStuById(id)) {//如果id有重复的话就不能添加此学生记录 
	       return true;//返回true 
	    }
	}
	return false;//遍历完学生列表也没有发现与待添加的学生记录冲突的学号，就返回false表示可以添加 
}

bool findStudentByID(vector<TelecomStudent> students, string id) {//根据id查找学生信息，模糊查询 
    bool found = false;//查找标志 
    for (auto& student : students) {//遍历学生信息
        if (student.matchID(id)) {//判断是否与需要查找的id匹配成功 
            student.displayInfo();//匹配成功，显示出此学生信息 
            found = true;//查找标志设为true 
        }
    }
    if (!found) {//遍历完学生信息found还是为false，表示未找到此学生 
        cout << "未找到id为 " << id << " 的学生！" << endl;
    }
    return found;
}

void findStudentByName(vector<TelecomStudent> students, string name) {//根据姓名查找学生信息，模糊查询 
    bool found = false;//查找标志 
    for (auto& student : students) {//遍历学生信息 
        if (student.matchName(name)) {//判断是否与需要查找的姓名匹配成功 
            student.displayInfo();//匹配成功，显示出此学生信息 
            found = true;//查找标志设为true 
        }
    }
    if (!found) {//遍历完学生信息found还是为false，表示未找到此学生 
        cout << "未找到姓名为 " << name << " 的学生！" << endl;
    }
}

void deleteStudentByID(vector<TelecomStudent>& students, string id) {//根据id删除学生信息
    for (auto it = students.begin(); it != students.end(); ++it) {//遍历学生信息 
        if ((*it).findStuById(id)) {//判断是否找到此id的学生 
            students.erase(it);//使用erase函数删除当前找到学生 
            cout << "id为 " << id << " 的学生已被成功删除！" << endl;
            return;
        }
    }
	//遍历完学生信息，还没return，表示未找到此学生 
    cout << "未找到id为 " << id << " 的学生！" << endl;
}

void modifyStudentByID(vector<TelecomStudent>& students, string id) {//根据id修改学生信息
	string name, className;
    char gender;
    double mathScore, englishScore;
    bool found = false;//查找标志 
    for (auto it = students.begin(); it != students.end(); ++it) {//遍历学生信息 
        if ((*it).findStuById(id)) {//判断是否与需要查找的id匹配成功 
            (*it).modifyInfo();//调用修改函数 
            found = true;//查找标志设为true 
        }
    }
    if (!found) {//遍历完学生信息found还是为false，表示未找到此学生 
        cout << "未找到id为 " << id << " 的学生！" << endl;
    }
}



int main() {
    vector<TelecomStudent> students;//创建一个学生容器，存储学生信息 
	string id, name, className;
    char gender;
    double mathScore, englishScore;
    // 添加学生信息
    students.emplace_back("2021001", "张三", 'F', "ClassA", 85.5, 78.0);
    students.emplace_back("2021002", "李四", 'M', "ClassA", 90.0, 85.0);
	students.emplace_back("2021003", "王五", 'M', "ClassB", 93.0, 68.0);
    int choice;
    do {
    	cout << "\n-----------------------------------" << endl;
        cout << "#        1、增加学生信息          #\n";
        cout << "#        2. 显示所有学生信息      #\n";
        cout << "#        3、查找学生信息          #\n";
        cout << "#        4、修改学生信息          #\n";
        cout << "#        5、删除学生信息          #\n";
        cout << "#        6、排序学生信息          #\n";
        cout << "#        0、退出                  #\n";
        cout << "-----------------------------------" << endl;
        cout << "请输入你的选择：";
        cin >> choice;

        switch (choice) {//使用switch-case结构实现对输入的选择进行相应的功能操作 
            case 1: {
                cout << "请输入学生id: ";
                cin >> id;//输入学生的id 
                while (isDuplicateID(students, id)) {//while循环判断输入的id是否已经在已有的学生信息中存在，如果存在就要一直输入id，直到输入一个不存在的id，因为每个学生的id是惟一的 
			        cout << "此id已经存在，请重新输入学生id: ";
			        cin >> id;
			    }
                cout << "请输入学生姓名: ";
                cin >> name;
                cout << "请输入学生性别: ";
                cin >> gender;
                cout << "请输入学生班级: ";
                cin >> className;
                cout << "请输入高数成绩: ";
                cin >> mathScore;
                cout << "请输入英语成绩: ";
                cin >> englishScore;
                students.emplace_back(id, name, gender, className, mathScore, englishScore);//将刚输入的信息加入到已有学生列表的末尾 
                break;
            }
            case 2: {
            	cout << "所有学生信息如下：\n";
                for (auto& student : students) {//遍历学生列表 
                    student.displayInfo();//显示学生信息 
                }
                break;
            }
            case 3: {
            	int choice1;
            	while(1){
            		cout << "\n-------------------------" << endl;
            		cout << "|    1、根据学号查询    |\n";
            		cout << "|    2、根据姓名查询    |\n";
					cout << "|    0、退出查询        |\n";
					cout << "-------------------------" << endl;
					cout << "请输入你的选择：";
					cin >> choice1;
					if(choice1 == 0){
						break;//退出查询循环 
					}else if(choice1 == 1){
						cout << "请输入需要查找的学生id：";
		                cin >> id;
		                findStudentByID(students, id);//调用根据id查找函数 
					}else if(choice1 == 2){
						cout << "请输入需要查找的学生姓名：";
		                cin >> name;
		                findStudentByName(students, name);//调用根据姓名查找函数 
					}else{
						cout << "请输入正确的选项！\n";
					}
				} 
                break;
            }
            case 4: {
            	cout << "请输入需要修改的学生id：";
		        cin >> id;
		        modifyStudentByID(students, id);//调用修改函数 
				break;
			}
			case 5: {
				cout << "请输入需要删除的学生id：";
		        cin >> id;
		        deleteStudentByID(students, id);//调用删除函数 
				break;
			}
            case 6: {//sort是c++自带的排序函数         //调用自定义的排序规则 
                sort(students.begin(), students.end(), TelecomStudent::compareScores);//调用排序函数，排序规则使用自定义的compareScores方法 
                cout << "以下是排序后的学生信息：\n";
				for (auto& student : students) {
                    student.displayInfo();
                }
                break;
            }
            default:
                cout << "无效的选择，请重新输入：\n";
        }
    } while (choice != 0);
    // 释放动态分配的内存
    for(TelecomStudent stu: students){
    	stu.~TelecomStudent();
	}
	cout<< "程序已退出！\n";
    return 0;
}